﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace Haidou.Wpf.Util.InterProcessChannel
{
	/// <summary>
	/// 管道服务器
	/// </summary>
	/// <typeparam name="TMessage"></typeparam>
	public class PipeServer<TMessage> : IDisposable
	{
		private readonly NamedPipeServerStream _pipe;
		private readonly StreamReader _reader;
		private readonly SynchronizationContext _synchronizationContext;
		private readonly CancellationTokenSource _source;

		public event EventHandler<TMessage> MessageReceived;

		public PipeServer(string pipeName)
		{
			_source = new CancellationTokenSource();
			_pipe = new NamedPipeServerStream(pipeName, PipeDirection.In);
			_reader = new StreamReader(_pipe, Encoding.UTF8);
			_synchronizationContext = SynchronizationContext.Current;

			//在线程池中启动循环。这将在应用程序的持续时间内运行，但是不应该使用LongRunning选项，因为线程不会一直被使用。
			_ = Task.Run(ServerLoop).ContinueWith(t => OnServerError(t.Exception), default, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.FromCurrentSynchronizationContext());
		}

		public void Stop()
		{
			_source.Cancel();
			_pipe.Disconnect();

			Dispose();
		}

		private async void ServerLoop()
		{
			while (true)
			{
				await _pipe.WaitForConnectionAsync(_source.Token);

				TMessage? message = await JsonSerializer.DeserializeAsync<TMessage>(_pipe, (JsonSerializerOptions)null, _source.Token);

				_pipe.Disconnect();

				if (message != null)
				{
					_synchronizationContext.Post(OnMessageReceived, message);
				}
			}
		}

		protected virtual void OnMessageReceived(object state)
		{
			MessageReceived?.Invoke(this, (TMessage)state);
		}

		protected virtual void OnServerError(AggregateException exception)
		{
			LogWriter.Log(exception, "IPC Server error.||IPC服务器错误");
		}

		public void Dispose()
		{
			_pipe.Dispose();
			_reader.Dispose();
			_source.Dispose();
		}
	}
}
